.TITLE RDDRV .IDENT /05.00/ ;+ ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; This software is furnished under a license and may be used ; or copied only in accordance with the terms of such license. ; ; Modified by: ; ; B. S. McCarthy 3-OCT-82 3.1 ; ; BM258 -- correct driver to use $CKBFB for buffer ; checking due to P.IOC ; ; Modified for RSX-11M-PLUS V4.5 by: ; ; D. Carroll 26-April-1995 04.00 ; DC360 -- vectoring common (always used) drivers ; ; Modified for RSX-11M-PLUS V4.6 by: ; ; D. Carroll 18-Oct-1995 05.00 ; DC404 -- Correct problem in powerfail routine which ; corrupts the system stack on the second power- ; fail ... ; ; ; Reconfiguration control driver ; ;+ ; The reconfiguration control driver provides the interface between ; user command level tasks which generate requests to perform system ; reconfiguration functions and to return system status indications and ; a priviledged reconfiguration control task. ; This driver access and address checks QIO requests from the command ; tasks, enqueues them into the recieve queue of the reconfiguration ; task, and initiates its execution. ; Except in the case of access errors, I/O completion is performed ; directly by the reconfiguration task. ;- ; ; Local macro definitions ; ; VC$RD ==0 ; RD: is now vectored LD$RD ==0 ; RD: is loadable .MCALL OLRDF$,UCBDF$ OLRDF$ ; Define online reconfiguration interface UCBDF$ ; Define UCB offsets ; ; Define local variables ; U.LIST=U.CNT+2 ; Listhead for packet extension ; ; Driver dispatch table ; DDT$ RD,1,NONE ; Define driver dispatch table ;+ ; Executive vector table for rddrv ;- EXEVEC: .WORD D.VINT ; executive vector table GTPKT:: .WORD $GTPKT ; Get I/O packet SSTS:: .WORD S.STS ; Controller status ALOCB:: .WORD $ALOCB ; allocate primary pool block DEACB:: .WORD $DEACB ; deallocate primary pool HRCPT:: .WORD $HRCPT ; pointer for hrc... TCB QRMVF:: .WORD $QRMVF ; Queue remove fifo QINSF:: .WORD $QINSF ; Queue insert fifo EXRQN:: .WORD $EXRQN ; activate task ... CKBFB:: .WORD $CKBFB ; check buffer EXRQP:: .WORD $EXRQP ; Activate and queue priority GTWRD:: .WORD $GTWRD ; get word from control buffer IOFIN:: .WORD $IOFIN ; finish I/O packet QINSP:: .WORD $QINSP ; queue insert priority RELOC:: .WORD $RELOC ; relocate and convert to address doubleword EXEND: ;+ ; **-RDINI- Reconfiguration driver initiatior entry point ; ; ; This routine is entered from the queue I/O directive each time a ; reconfiguration command task issues a qio to a LUN assigned to the ; RD0: unit. The command task supplies one or two buffer address and ; size descriptors and a function code. The QIO directive code has ; validated the first buffer and placed the two-word buffer descriptor ; at offsets i.buf+0 and i.buf+2 in the packet. This driver is called ; directly from the directive service code to validate the additional ; parameters. The packet is then queued to the SCB I/O request queue ; for the unit and a call made to $GTPKT to dequeue the next request ; in that queue. ; ; Inputs: ; R1= address of I/O packet ; R4= address of SCB ; R5= address of UCB ; ; The packet is formatted as follows: ; ; i.lnk: I/O queue thread word ; i.pri: request priority ; i.efn: event flag number ; i.TCB: address of tcb of requestor task ; i.ln2: address of LUN2 word in header of requestor task ; i.UCB: address of ucb ; i.fcn: I/O function code ; i.iosb: virtual address of I/O status block ; +2: relocation bias of I/O status block ; +4: displacement of I/O status block (relative to apr6) ; i.AST: virtua address of ast service routine ; i.prm: relocation bias of first I/O buffer ; +2: displacement to first I/O buffer (relative to apr6) ; +4: size in bytes of first I/O buffer ; +6: ; +10: ; +12: ; +14: ; +16: ; ; I/o function codes serviced by this driver: ; ; io.mfc = 0,1 multiple functions and I/O parameters are supplied ; in the users buffer ; io.rsc = 0,2 read system configuration ; io.att = 0,3 attach to unit ; io.det = 0,4 deatach from unit ; io.wsc = n,6 write system configuration ; 'n' is a function code. ; ;- RDINI: TST EXEVEC ; vectors translated? BNE 10$ ; if NE, yes, continue MOV R1,-(SP) ; Save packet address MOV R4,-(SP) ; and SCB address CALL RDPWF ; translate executive vectors MOV (SP)+,R4 ; restore SCB MOV (SP)+,R1 ; and IOP 10$: MOV R1,R3 ; Copy address of packet ADD #I.FCN,R1 ; And point to function code CMPB #IO.ATT/400,1(R1) ; Attach? BEQ 95$ ; Yes, go enqueue CMPB #IO.DET/400,1(R1) ; How about a detach? BEQ 95$ ; Yes, same operation. CMP #IO.RSC,(R1) ; Is this a 'read full configuration'? BEQ 95$ ; Yes, then just go enqueue request CMP #IO.HRC,(R1) ; Is this a mode-change command? BEQ 140$ ; Br if yes MOV #IE.RSU&377,R0 ; Assume this caller is not attached. ; For the remainder of the functions the caller ; must be attached before the request is ; enqueued. This serves to guarentee ; continutity of access ; if more than one requestor is simultaniously ; attempting to address the reconfiguration ; task. CMP I.TCB(R3),U.ATT(R5) ; Is this caller attatched yet? BNE 125$ ; Go issue I/O error return 20$: MOV R3,-(SP) ; Save packet address MOV R3,-(SP) ; Twice. MOV R3,U.BUF+2(R5) ; Setup for call to $getwrd, point into packet ADD #I.PRM,U.BUF+2(R5) ; Point to first parameter in packet ;+ ; ; Come here if this is either a 'write device configuration' or ; 'multiple function' ; ;- 30$: MOV #14,U.CNT(R5) ; Count of remaining bytes in the packet. CMP #IO.MFC,I.FCN(R3) ; Multi-function qio? BNE 40$ ; Br if not ;+ ; Change input buffer descriptor to reference user supplied buffer ;- ADD #I.PRM+0,R3 ; Point to first parameter MOV (R3)+,U.BUF+0(R5) ; Set address for $gtwrd MOV (R3)+,U.BUF+2(R5) ; Referencing the users multi-function MOV (R3),U.CNT(R5) ; Buffer. 40$: ; At this point U.BUF/U.CNT refer to either ; the remainder of the parameters in the ; packet itself (for a io.wsc function) or ; to the users specification buffer (for an ; IO.MFC function) MOV #IE.BAD&377,R0 ; Assume the caller supplied a too-large buffer CMP U.CW3(R5),U.CNT(R5); Check against maximum parameters BLO 120$ ; Br if buffer too big CALL NXTNOD ; Allocate the first packet extension node ; And link it to the packet extension list. BCS 110$ ; Br if allocation error 50$: MOV (SP),R1 ; Get packet address again BEQ 150$ ; Br if this was a oneshot qio (io.wsc) ; and we have finished parameter processing MOV I.FCN(R1),R0 ; Get user function code SWAB R0 ; Get function code to low byte CMPB #IO.WSC/400,R0 ; Single operation? BNE 60$ ; No, br if multi-operation CLR (SP) ; Flag single operation complete BR 70$ ; 60$: ; Pickup true function code ; From the user command buffer CALL GETWRD ; Get next word from user multi-function buffer BCS 150$ ; Br if end of buffer MOV R1,R0 ; Position funcion code SWAB R0 ; Get function code to low byte ;+ ; Validate next function code ;- 70$: CMPB #IO.WSC/400,R0 ; This must be a write configuration function BNE 100$ ; Illegal function SWAB R0 ; Get subfunction CMPB #MAXFC,R0 ; Verify code is in range BLO 100$ ; Illegal function code CALL PUTWRD ; Put function code to packet extension list BCS 110$ ; Br if allocation error CLR R1 ; Count required parameters BIC #^C377,R0 ; Isolate command BEQ 100$ ; Br if illegal function MOVB LEGFCN-1(R0),R0 ; Pickup control byte MOV R0,-(SP) ; Save for second half CALL MOVPAR ; Copy parameters if any MOV (SP)+,R0 ; Get control word back BCS 110$ ; Br if parameter error ASH #-4,R0 ; Shift to second quartet CALL MOVDES ; Copy descriptors if any BCS 110$ ; Br if parameter error BR 50$ ; Go for next command 80$: MOV #IE.SPC&377,R0 ; Parameter error BR 120$ ; Take error exit 95$: BR 170$ ; Relay branch from above 100$: MOV #IE.IFC&377,R1 ; Illegal function code 110$: MOV R1,R0 ; Code was set by detecting routine above 120$: TST (SP)+ ; Remove flag word MOV (SP)+,R3 ; Get packet address 125$: CLR R1 ; Reset second word of I/O status return CALL @IOFIN ; And return error status ; ; Now clear any partial packet extension list built above ; 130$: MOV R5,R0 ; Point to listhead ADD #U.LIST,R0 CALL @QRMVF ; Remove next node BCS 200$ ; Br if no more in list MOV R1,R0 ; Set address of node to return MOV #I.LGTH,R1 ; And set allocated size CALL @DEACB ; Return node to system pool BR 130$ ; Go for next in list ; ; Process privileged task mode change request ; 140$: MOV I.TCB(R3),R2 ; Pick up requestor TCB address BIT #T3.PRV,T.ST3(R2) ; Is it privileged? BEQ 146$ ; Br if no. non-privileged requestors ; Just wake up hrc... ADD #I.PRM+0-I.FCN,R1 ; Advance pointer to first parameter BIC (R1),U.CW2(R5) ; Reset 'mask' from mode bits COM (R1) ; Obtain 'not mask' BIC (R1)+,(R1) ; And ensure 'true' bits dont contain any ; Other than what were specified in 'mask' BIS (R1),U.CW2(R5) ; And set in new bits into mode control. 146$: MOV #IS.SUC,R0 ; Set status CLR R1 ; Set second status value TST @HRCPT ; Does hrc exist? BNE 147$ ; Br if not MOV #IE.OFL&377,R0 ; Revise status accordingly 147$: CALL @IOFIN ; And terminate I/O operation MOV @HRCPT,R0 ; Pick up TCB address for hrc BEQ 200$ ; Ignore operation of hrc not installed CALLR @EXRQN ; Request hrc to check new mode ; ; The final command has been transferred to the packet extension ; 150$: CLR R0 ; Set a zero command as a stopper in the ; Packet extension CALL PUTWRD ; Put to extension list BCS 110$ ; Br if allocation error 160$: TST (SP)+ ; Remove flag MOV (SP)+,R3 ; Get packet address ; ; Copy packet extension listhead to the packet and enqueue the packet ; To the SCB queue. ; 170$: MOV R3,R1 ; Restore packet adderss MOV U.LIST+0(R5),I.PRM+14(R1) ; Copy extension listhead to packet 175$: CLR U.LIST(R5) ; MOV R5,U.LIST+2(R5) ; Reset listhead ADD #U.LIST,U.LIST+2(R5) ; To empty MOV U.SCB(R5),R0 ; Point to I/O queue listhead CALL @QINSP ; And insert packet in queue ; Fall through into packet dequeue ; ; Fetch the next packet from the input queue ; Perform attach and detach functions as a side effect ; 180$: BICB #US.BSY,U.STS(R5) ; Mark driver not busy MOV U.SCB(R5),R4 ; Get SCB address ADD SSTS,R4 ; Adjust to status word CLRB (R4) ; To allow another dequeue GTPKT$ RD,1,130$,,T ; Get next packet from queue or return to caller ;+ ; Input: ; R1= address of next packet ; R4= address of SCB ; R5= address of UCB ; ; Packet format: ; ; as above. ;- MOV @HRCPT,R0 ; Get address of hrc processing task BNE 190$ ; Br if service task available MOV #IE.OFL&377,R0 ; 'device' offline MOV R1,R3 ; Set up for $iofin MOV I.PRM+14(R1),R2 ; Get address of first node BEQ 187$ ; No list, go take error exit MOV R2,U.LIST+0(R5) ; Build listhead 185$: MOV R2,U.LIST+2(R5) ; LAST node pointer MOV (R2),R2 ; Look for real lAST node BNE 185$ ; Not yet 187$: CALL 125$ ; Do I/O done on this packet and ; Elimenate any parameter lists BR 180$ ; Go reset device not busy and ; Check for another packet 190$: CALL @EXRQP ; Enqueue to hrc and activate if not already BR 180$ ; Go for next packet ;+ ; Powerfail and timeout driver entry points ;- 200$: RDOUT: RDCAN: RETURN RDPWF: TST EXEVEC ; Vector table translated? BNE 80$ ; if ne, yes MOV R5,-(SP) ; save our UCB address MOV KINAR6,-(SP) ; Save Kernel-I apr6 MOV @#112,R0 ; Get address of table of entries MOV @(R0),KINAR6 ; Map common through i-space apr6 MOV #EXEVEC,R3 ; Point to our vector table MOV #</2>-1,R2 ; set up the length CALL @#140004 ; Translate the vector table MOV (SP)+,KINAR6 ; Restore Kernel-I apr6 MOV (SP)+,R5 ; Restore our UCB ;DC404 80$: RETURN ; All done ;DC404 ;**-2 ;+ ; Utility routines ;- ;+ ; Copy parameters or buffer descriptors to extension as indicated ; In the control byte. ;- MOVPAR: BIC #^C17,R0 ; Isolate control bits BEQ 15$ ; Br if done MOV R0,R2 ; Copy parameter count 10$: CALL GETWRD ; Get next word from user buffer BCS 15$ ; Br if no more parameters MOV R1,R0 ; Copy for put CALL PUTWRD ; Put it to the packet extension BCS 15$ ; Br if node allocation error SOB R2,10$ ; Loop for all parameters 15$: RETURN MOVDES: BIC #^C17,R0 ; Isolate count of descriptors BEQ 35$ ; Br if none to move MOV R5,-(SP) ; Save a register MOV R0,-(SP) ; Save the count 10$: CALL GETBUF ; Get next buffer descriptor from user buffer BCS 28$ ; Branch if input exhausted prematurely MOV R0,-(SP) ; Save buffer size MOV R1,R0 ; Set buffer relocation address (apr6) CALL PUTWRD ; Put to extension BCS 25$ ; Br if allocation error MOV R2,R0 ; Put relocation offset CALL PUTWRD ; And put it to the packet extension BCS 25$ ; Br if allocation error MOV (SP),R0 ; Set buffer length CALL PUTWRD ; And put it to the packet extension 25$: INC (SP)+ ; Clear stack without changing carry bit BCS 30$ ; Exit if error DEC (SP) ; Dec count of descriptors BNE 10$ ; Loop 28$: INC (SP)+ ; Clean the stack 30$: MOV (SP)+,R5 ; Restore a register 35$: RETURN ; ; ; Get a buffer descriptor from the user, address check and relocate ; To an apr6 base plus offset. ; GETBUF: CALL GETWRD ; Get virtual address of buffer BCS 50$ ; Br if no more MOV R1,R0 ; Set address CALL GETWRD ; Get size word BCS 50$ ; Br if no more MOV R1,-(SP) ; Save size for return BNE 5$ ; Br if real descriptor CLR R2 ; Indicate no buffer available BR 40$ ; Complete scan 5$: CALL @CKBFB ; Check and lock the buffer BCS 40$ ; And exit if there is a buffer mapping error CALL @RELOC ; And relocate to apr6 offset 40$: MOV (SP)+,R0 ; Return buffer size 50$: RETURN ;+ ; Get next word from user input buffer or packet. ;- GETWRD: MOV #IE.BAD&377,R1 ; Assume fetch error SUB #2,U.CNT(R5) ; Account for word taken BCS 10$ ; Br if no more CALL @GTWRD ; User system routine to address the buffer MOV (SP)+,R1 ; Load value CLC ; Ensure carry clear 10$: RETURN ;+ ; Put word to packet extension list ; ; Input: ; R0=word to put ; R3=bytecount of space remaining in node ; R4=node fill pointer ;- PUTWRD: SUB #2,(R3) ; Account for space taken BGE 20$ ; Br if space is available ADD #2,(R3) ; Correct underflow CALL NXTNOD ; Allocate next node and link it to the ; Extension list BCC PUTWRD ; Try again BR 30$ ; Allocate error 20$: MOV R0,(R4)+ ; Put word to node 30$: RETURN ; ; Allocate another node for the packet extension list and link it to the ; Listhead at u.list+0,+2 ; NXTNOD: JSR R2,$SAVVR ; Save r0,r1,r2 MOV #I.LGTH,R1 ; Set size of extension node MOV R1,R3 ; Set fill count CALL @ALOCB ; Allocate node BCS 10$ ; Br if allocate error MOV R0,R4 ; Set fill pointer MOV R0,R1 ; And node address MOV R5,R0 ; Set listhead address ADD #U.LIST,R0 ; CLR (R4)+ ; Zero linkword MOV R3,(R4) ; Set 'space remaining' MOV R4,R3 ; Copy pointer to 'space remaining' SUB #4,(R4)+ ; Adjust to actual space and point to ; First fill location MOV R3,-(SP) ; Against modification CALL @QINSF ; Insert node at end of extension list MOV (SP)+,R3 ; Restore registers RETURN 10$: MOV #IE.NOD&377,R1 ; Allocation error RETURN ; ; Specification of legal functions and arguments ; .MACRO CMD NAME $$$TMP=. .=LEGFCN+-1 .BYTE IO$'NAME&377 .IIF GT .-$$$TMP $$$TMP=. .=$$$TMP $$$CNT=$$$CNT+1 .ENDM $$$CNT=0 LEGFCN: CMD ONL ; Online, two buffer descriptors CMD OFL ; Offline, two buffer descriptors CMD MAI ; Maintenance, two buffer descriptors CMD ONE ; On condition CMD IF ; If condition CMD CAC ; Cache control, one parameter CMD MEM ; Mind control, one descriptor,one parameter CMD HRC ; Control - set hrc operating modes CMD STN ; Set task name two words CMD STA ; Return device status CMD RLI ; Link, two descriptors CMD RUL ; Unlink, one descriptor CMD MBO ; Memory box online, 2 parameters and 4 descriptors CMD MBF ; Memory box offline CMD RSW ; Switch, two descriptors CMD WAT ; Write attributes, 1 descriptor CMD RAT ; Read attributes, 1 descriptor ASSUME $$$CNT,<<.-LEGFCN>> ; Ensure no commands were left out MAXFC=.-LEGFCN .END